if (!window.HTTP) {
    window.HTTP = {};
}

HTTP._factories = [
    function() { return new XMLHttpRequest(); },
    function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
    function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
];

// When we find a factory that works, store it here.
HTTP._factory = null;
HTTP.newRequest = function() {
    if (HTTP._factory != null) return HTTP._factory();

    for(var i = 0; i < HTTP._factories.length; i++) {
        try {
            var factory = HTTP._factories[i];
            var request = factory();
            if (request != null) {
                HTTP._factory = factory;
                return request;
            }
        }
        catch(e) {
            continue;
        }
    }
    HTTP._factory = function() {
        throw new Error("XMLHttpRequest not supported");
    }
    HTTP._factory(); // Throw an error
}
HTTP.encodeFormData = function(data) {
    var pairs = [];
    var regexp = /%20/g; // A regular expression to match an encoded space

    for(var name in data) {
        var value = data[name].toString();
        var pair = encodeURIComponent(name).replace(regexp,"+") + '=' +
            encodeURIComponent(value).replace(regexp,"+");
        pairs.push(pair);
    }
    return pairs.join('&');
};
HTTP._getResponse = function(request) {
    switch(request.getResponseHeader("Content-Type")) {
    case "text/xml":
        return request.responseXML;
    case "text/json":
    case "text/javascript":
    case "application/javascript":
    case "application/x-javascript":
        return eval("(" + request.responseText + ")");
    default:
        return request.responseText;
    }
};

/**
 * options = {"parameters": {queryname:value,...}, "values": {postname:value,...},
 *            "timeout": miliseconds, "timeoutHandler": timeoutFunc, "progressHandler": progressFunc}
*/
HTTP.sendRequest = function(method, url, callback, options) {
    var request = HTTP.newRequest();
    var n = 0;
    var timer;
    if (options && options.timeout)
        timer = setTimeout(function() {
                               request.abort();
                               if (options.timeoutHandler)
                                   options.timeoutHandler(url);
                           }, options.timeout);

    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            if (timer) clearTimeout(timer);
            if (request.status == 200) {
                if (callback) callback(HTTP._getResponse(request));
            }
            else {
                if (options && options.errorHandler)
                    options.errorHandler(request.status,
                                         request.statusText);
                else if (callback) callback(null);
            }
        }
        else if (options && options.progressHandler) {
            options.progressHandler(++n);
        }
    };

    var target = url;
    if (options && options.parameters)
        target += "?" + HTTP.encodeFormData(options.parameters);
    request.open(method, target);
    var values = null;
    if (method == "POST") {
        request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        if (options && options.values)
            values = HTTP.encodeFormData(options.values);
    }
    request.send(values);
};

HTTP.get = function(url, callback, options) {
    HTTP.sendRequest("GET", url, callback, options);
};
HTTP.post = function(url, callback, options) {
    HTTP.sendRequest("POST", url, callback, options);
};